package com.dycx.api.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.JWTValidator;
import com.dycx.cms.entity.AdDO;
import com.dycx.cms.service.AdService;
import com.dycx.common.CounterLimiter;
import com.dycx.common.RestResponse;
import com.dycx.common.rabbitmq.provider.MessageMq;
import com.dycx.common.vendor.map.feign.GaoDeApiClient;
import com.dycx.message.service.MessageService;
import com.dycx.message.vendor.dto.MessageContentDTO;
import com.dycx.message.vendor.dto.RecipientDTO;
import com.dycx.system.constants.AdminConstants;
import com.dycx.system.service.PermissionService;
import com.dycx.system.service.RegionService;
import com.dycx.system.service.RoleService;
import org.apache.commons.codec.digest.DigestUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping(value = "/test")
public class TestController {

    @Resource
    private GaoDeApiClient gaoDeApiClient;
    @Resource
    private RegionService regionService;

    @Resource
    private MessageService messageService;

    @Resource
    private AdService adService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;


    @Autowired
    private RedissonClient redissonClient;

    @Resource
    private PermissionService permissionService;

    @Resource
    private RoleService roleService;


//    @Resource
//    private OssConfig2 ossConfig2;

//    @Autowired
//    public void TestController(OssConfig2 ossConfig2) {
//        this.ossConfig2 = ossConfig2;
//    }

    @Value("${oss.endpoint}")
    private String endpoint;

    @GetMapping("/test")
    public void test(String arrangeSectionCode) {

//        arrangeSectionSeatService.updateSeatStatus(arrangeSectionCode, null, null);

//        TicketOrderDO entity = new TicketOrderDO();
//        entity.setStartAddress("AAAAAAAAAAAAAAAA");
//
//        TicketOrderDO vo = new TicketOrderDO();
//        BeanUtil.copyProperties(entity, vo);
//        vo.setEndAddress("BBBBBBBBBBBBBBB");
//
//        System.out.println("-------startAddress-----------");
//        System.out.println(entity);
//        System.out.println("-------endAddress-----------");
//        System.out.println(vo);

    }

    @GetMapping("/batchAdd")
    public String batchAdd() {
        permissionService.batchAdd();
        return "添加成功！";
    }


    @GetMapping("/createJwt")
    public String createJwt() {
        return DigestUtils.md5Hex("Wzb@@123" + AdminConstants.PASSWORD_SALT);
//        //创建token
//        Map<String,Object> map = new HashMap<>();
//        map.put("username","吴宗兵");
//        String token = JWT.create()
//                .addPayloads(map)
//                .setExpiresAt(DateUtil.offsetSecond(DateUtil.date(), 30)) //指定令牌过期时间
//                .sign(JWTSignerUtil.hs256(AdminConstants.JWT_KEY.getBytes()));//签名
//        return token;
    }

    @GetMapping("/getJwt")
    public RestResponse getJwt(String token) {
        final JWT jwt = JWTUtil.parseToken(token);

        return RestResponse.success(jwt.getPayloads());
    }

    @GetMapping("/verifyJwt")
    public RestResponse verifyJwt(String token) {
        try {
            JWTUtil.verify(token, AdminConstants.JWT_KEY.getBytes());//验证令牌
            return RestResponse.success("验证成功");
        } catch (Exception e) {
            return RestResponse.notLogin(e.getMessage());
        }
    }

    @GetMapping("/verifyJwtTime")
    public RestResponse verifyJwtTime(String token) {
        try {
            JWTValidator.of(token).validateDate(DateUtil.date());
            return RestResponse.success("验证成功");
        } catch (Exception e) {
            return RestResponse.notLogin(e.getMessage());
        }
    }

    @GetMapping("/sleep")
    public void upload() {
        try {
            System.out.println(LocalDateTime.now());
            Thread.sleep(5000);

            System.out.println(LocalDateTime.now());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    //http://localhost:8080/test/districtApi?keywords=530000

//    @GetMapping("/districtApi")
//    public void districtApi(String keywords) {
//        GaoDeResultDTO res = gaoDeApiClient.getDistrict(key, keywords);
//
//        regionService.syncAMapData(res.getDistricts(), 0);
//    }

    @GetMapping("/send")
    public void send() {
        RecipientDTO recipient = new RecipientDTO();
        List<String> phone = new ArrayList<>();
        phone.add("18288282428");

        recipient.setPhone(phone);

        List<String> templateParam = new ArrayList<>();
        templateParam.add("5321");
        MessageContentDTO messageContentDTO = new MessageContentDTO();
        messageContentDTO.setSms(templateParam);
        messageService.sendMessage(2, recipient, messageContentDTO);
    }

//    @GetMapping("/feign")
//    public String feign() {
//        return mpClient.openInvoice();
//    }

    @GetMapping("/sendMq")
    public void sendMessage() {
        MessageMq.sendCreateMessage("33333333333333");
    }

    /**
     * 并发测试，分步式锁，解决重复数据、超卖问题
     *
     * @param num
     * @return
     */
    @GetMapping("/bingFa")
    public Object bingFa(int num) {
        RLock rLock = redissonClient.getLock("lockName" + num);
        try {
            boolean isLocked = rLock.tryLock(30, 60, TimeUnit.SECONDS);
            if (!isLocked) {
                return "失败1---";
            }

//                LambdaQueryWrapper<AdDO> wrapper = new LambdaQueryWrapper<>();
//                wrapper.eq(AdDO::getTitle, "重复插入并发测试");
//                wrapper.last("limit 1");
//                AdDO adDO = adService.getOne(wrapper);
//
//                if (ObjectUtil.isNotNull(adDO)) {
//                    return "数据已存在";
//                }

            AdDO adDO = adService.getById(60);
            adDO.setSort(adDO.getSort() + 1);
            adService.updateById(adDO);
            return RestResponse.success("并发测试");

        } catch (Exception e) {
            return "失败2";
        } finally {
//            rLock.unlock();
        }
    }

    /**
     * 并发限流
     *
     * @param num
     * @return
     */
    @GetMapping("/bingFa/flow")
    public Object flow(int num) {

//        String storageStr = stringRedisTemplate.opsForValue().get("storage");
//        int storage = StrUtil.isBlank(storageStr) ? 0 : Integer.parseInt(storageStr);
//        if (storage >= 10) return "已售罄";
//        stringRedisTemplate.opsForValue().set("storage", Convert.toStr(storage + 1));


        RLock rLock = redissonClient.getLock("lockName" + num);
        try {
            boolean isLocked = rLock.tryLock(30, 60, TimeUnit.SECONDS);
            if (!isLocked) return "系统繁忙，请稍后再试";

            AdDO adDO = adService.getById(60);
            if (adDO.getSort() >= 10) return "已售罄";

            Thread.sleep(5000);
            adDO.setSort(adDO.getSort() + 1);
            adService.updateById(adDO);

            return RestResponse.success("当前请求成功");

        } catch (Exception e) {
            return "失败2";
        } finally {
            rLock.unlock();
        }
    }

    /**
     * 并发限流
     *
     * @param num
     * @return
     */
    @GetMapping("/bingFa/limitFlow")
    public Object limitFlow(Integer num) {
        CounterLimiter cl = new CounterLimiter(num);

        try {
            if (cl.allowRequest()) {
                Thread.sleep(1000);
                System.out.println("c-A:" + cl.getCounter());
                System.out.println("c-B:下单成功");

                return RestResponse.success("下单成功！");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("s-A:" + cl.getCounter());
        System.out.println("s-B:系统繁忙，请稍后再试！");

        return "系统繁忙，请稍后再试！";
    }
}
